#pragma once
#include "gtest/gtest.h"

#include "Utility/Logging/SGLogger.h"

#include "DataStructure/Common/Validation.h"

#include "DBManager/IService/Input/Dynamic/IEIGCService.h"
#include "DBManager/IService/Input/Parameter/IParameterService.h"

#include "Export/NH5Export/NH5Export.h"

#include "SGFem/ElementCalculator/Factory/ElementCalculatorFactory.h"
#include "SGFem/Task/Kernel/MModel.h"
#include "SGFem/Task/Modes/ComplexModalSolver.h"

#include "SGFem/Constraint/RElement/BoundaryCondition.h"

TEST (ComplexEigenValueTaskTest, ComplexModalCalculatorTest)
{
    // Input Data
    // 读取模型数据
    Project project;
    project.m_modelFilePath = SG::Utility::FileSystem::getTestDataPath ("SGFem/ModalAnalysis/");
    project.m_modelFileName = "Complex_Modal_a1_a2.bdf";
    project.m_jobName       = "Complex_Modal_a1_a2_result";
    project.m_workSpace     = ".";

    // 导入数据库
    DB_SERVICEFACTORY->ClearDatabase ();
    SG::Import::SGImporter importer (DB_SERVICEFACTORY);
    auto                   status = importer.Import (project.m_modelFilePath + project.m_modelFileName);
    ASSERT_EQ (status, Status::STATUS_Success);

    // 初始化
    auto           allSubcaseId = DB_SERVICEFACTORY->get<ISubcaseService> ()->GetAllSubcaseID ();
    auto           subcaseId    = allSubcaseId[0];
    Kernel::MModel ModelTest (SG::DataStructure::FEM::SOLType::SOL_SEDCEIG, DB_SERVICEFACTORY);
    ModelTest.Initialize (allSubcaseId);
    // ModelTest.CalcMatrixEquation (subcaseId);

    auto    para1 = DB_SERVICEFACTORY->get<ISubcaseService> ()->FindSubCase (subcaseId);
    Subcase subcase (para1);

    // Test data
    // 模态分析
    SG::DataStructure::FEM::EIGCData EIGCData;
    ASSERT_EQ (Status::STATUS_Success, DB_SERVICEFACTORY->get<IEIGCService> ()->FindBySId (subcase.GetCMethodId (), EIGCData));
    int ModesOrder = EIGCData.m_ND1;  // 求解阶数

    // Kernel::MModel           ModelTest (SG::DataStructure::FEM::SOLType::SOL_SEMODES, DB_SERVICEFACTORY);
    SG::Utility::SGParameter myParameter;
    myParameter.AddInt ("SubcaseID", subcaseId);
    myParameter.AddInt ("ModesOrder", ModesOrder);
    myParameter.AddString ("FrequencySelectionMode", "LM");  //"LM"：低频优先，"SM"：高频优先

    ComplexModalSolver solver;
    solver.Solve (DB_SERVICEFACTORY, project, subcaseId);

    // 输出结果矩阵，4行ModesOrder列
    std::vector<std::vector<Real>>                   modalTest (4, std::vector<Real> (ModesOrder, 0.0));
    std::vector<std::vector<SG::Algebra::Complex_t>> vectorTest (ModesOrder);
    for (int order = 1; order <= ModesOrder; ++order)
    {
        // Algebra::Complex_t eigen;
        SG::Algebra::Complex_t              eigen;
        Real                                freq, damp, spinSpeed;
        std::vector<SG::Algebra::Complex_t> vector;
        ModelTest.GetEigenValue (subcaseId, order, eigen, freq, damp, spinSpeed);
        ModelTest.GetEigenVector (subcaseId, order, vector);
        modalTest[0][order - 1] = eigen.real ();
        modalTest[1][order - 1] = eigen.imag ();
        modalTest[2][order - 1] = freq;
        modalTest[3][order - 1] = damp;

        vectorTest[order - 1] = vector;
    }

    // Target data
    std::vector<std::vector<Real>> modalTarget (4, std::vector<Real> (ModesOrder, 0.0));
    // REAL
    modalTarget[0] = { -5.1630918950552713, -5.1630918950552713 };
    // IMAG
    modalTarget[1] = { 42.878657163040309, -42.878657163040309 };
    // FREQUENCY
    modalTarget[2] = { 6.8243502406405705, 6.8243502406405705 };
    // DAMPING
    modalTarget[3] = { 0.24082339497822008, 0.24082339497822008 };

    std::vector<std::vector<SG::Algebra::Complex_t>> vectorTarget (ModesOrder);
    vectorTarget[0] = { { 1.0, 0.0 }, { 0.8507810593582128, 3.474958409544951E-18 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }

    };
    vectorTarget[1] = { { 1.0, 0.0 }, { 0.8507810593582128, -3.474958409544951E-18 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }, { 0.0, 0.0 },
                        { 0.0, 0.0 }

    };

    // Check
    for (int i = 0; i < 4; ++i)
    {
        for (int j = 0; j < ModesOrder; ++j)
        {
            ASSERT_NEAR (modalTest[i][j], modalTarget[i][j], 1.0e-6);
        }
    }

    for (int i = 0; i < ModesOrder; ++i)
    {
        ASSERT_EQ (vectorTest[i].size (), vectorTarget[i].size ());
        for (size_t j = 0; j < vectorTest[i].size (); ++j)
        {
            ASSERT_NEAR (vectorTest[i][j].real (), vectorTarget[i][j].real (), 1.0e-12);

            ASSERT_NEAR (vectorTest[i][j].imag (), vectorTarget[i][j].imag (), 1.0e-12);
        }
    }
}